#pragma once
#include <iostream>
#include <fstream>
#include <exception>
#include "math.h"
#include "string.h"


enum LexType
{
	ALPHA,
	COMMENT,
	PUNC,
	SEPARATOR,
	EOL,
	EOFF,
	REAL,
	INTEGER
};

/*
struct Lexeme{
	LexType type;
	union
	{
		char* alpha;
		char punctuation;
		double real;
		int integer;
	};
	friend std::ostream& operator << (std::ostream&, const Lexeme &);
};
*/
class Lexeme {
	public:
		LexType type;
		union
		{
			char* alpha;
			char punctuation;
			double real;
			int integer;
		};
		//inline ~Lexeme() {if(type == ALPHA) delete [] alpha;};
		inline Lexeme() {};
		inline Lexeme(const Lexeme& lex) {
										type = lex.type;
										if(lex.type == PUNC)
											punctuation = lex.punctuation;
										if(lex.type == REAL)
											real = lex.real;
										if(lex.type == INTEGER)
											integer = lex.integer;
										if(lex.type == ALPHA)
										{
											alpha = new char[strlen(lex.alpha)+1];
											strcpy(alpha, lex.alpha);
										}
									}
		inline Lexeme operator=(const Lexeme& lex) {
										type = lex.type;
										real = lex.real;
										if(lex.type == PUNC)
											punctuation = lex.punctuation;
										if(lex.type == REAL)
											real = lex.real;
										if(lex.type == INTEGER)
											integer = lex.integer;
										if(lex.type == ALPHA)
										{
											alpha = new char[strlen(lex.alpha)+1];
											strcpy(alpha, lex.alpha);
										}
										return *this;
									}
	friend std::ostream& operator << (std::ostream&, const Lexeme &);
};

class ParserException: public std::exception
{
	private:
		const std::string message;
	public:
	inline ParserException(const char* msg) : message(msg) {};
	inline ~ParserException() throw() {};
	inline virtual const char* what() { return message.c_str(); };
};

class ParserHelper
{
	public:
		static Lexeme lexer(std::ifstream& source);
	private:
		static bool isDigit(char c);
		static bool isAlpha(char c);
		static bool isSign(char c);
		static bool isPunctuation(char c);
		static bool isSeparator(char c);
		static bool isComment(char c);
};
